/*
 * @Author: Troubadour 2276791354@qq.com
 * @Date: 2024-07-28 20:30:13
 * @LastEditors: Troubadour 2276791354@qq.com
 * @LastEditTime: 2024-08-10 23:22:34
 * @Version:
 * @Description:
 */

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Include file                                                                       -
--------------------------------------------------------------------------------------------------------------------------------------*/
#include "ina226_app.h"
#include "ina226_obj.h"
#include "FreeRTOS.h"
#include "task.h"

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal macro                                                                     -
--------------------------------------------------------------------------------------------------------------------------------------*/


/* Configure measurement parameters of the INA226 MIN channel. */
/* Sampling resolution of the INA226 MIN channel, unit: Ω */
#define INA226_MIN_RES_VALUE        (0.08)
/* Maximum expected current, Unit ：A */
#define INA226_MIN_MAX_CURRENT      (1.0)
/* Sampling resolution of the INA226 MIN channel. */
#define INA226_MIN_CURRENT_LSB      (INA226_MIN_MAX_CURRENT / (double)0x8000)
/* Calculate calibration value. */
#define INA226_MIN_CAL_VALUE        (0.00512 / (INA226_MIN_CURRENT_LSB * INA226_MIN_RES_VALUE))

/* Configure measurement parameters of the INA226 MIN channel. */
/* Sampling resolution of the INA226 MIN channel, unit: Ω */
#define INA226_MED_RES_VALUE        (0.008)
/* Maximum expected current, Unit ：A */
#define INA226_MED_MAX_CURRENT      (10.0)
/* Sampling resolution of the INA226 MIN channel. */
#define INA226_MED_CURRENT_LSB      (INA226_MED_MAX_CURRENT / (double)0x8000)
/* Calculate calibration value. */
#define INA226_MED_CAL_VALUE        (0.00512 / (INA226_MED_CURRENT_LSB * INA226_MED_RES_VALUE))

/* Configure measurement parameters of the INA226 MIN channel. */
/* Sampling resolution of the INA226 MIN channel, unit: Ω */
#define INA226_MAX_RES_VALUE        (0.005)
/* Maximum expected current, Unit ：A */
#define INA226_MAX_MAX_CURRENT      (15.0)
/* Sampling resolution of the INA226 MIN channel. */
#define INA226_MAX_CURRENT_LSB      (INA226_MAX_MAX_CURRENT / (double)0x8000)
/* Calculate calibration value. */
#define INA226_MAX_CAL_VALUE        (0.00512 / (INA226_MAX_CURRENT_LSB * INA226_MAX_RES_VALUE))
/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal enum                                                                      -
--------------------------------------------------------------------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal structure                                                                 -
--------------------------------------------------------------------------------------------------------------------------------------*/

typedef struct
{
    INA226TypeDef *ina226_t[INA226_NUMBER];
    uint8_t measure_channel;
} INA226_CXT_T;

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal function                                                                  -
--------------------------------------------------------------------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal variables                                                                 -
--------------------------------------------------------------------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  External variables                                                                 -
--------------------------------------------------------------------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Function body                                                                      -
--------------------------------------------------------------------------------------------------------------------------------------*/

SoftAnalogIIC_Typedef ina226_min_iic_t = {0};
SoftAnalogIIC_Typedef ina226_med_iic_t = {0};
SoftAnalogIIC_Typedef ina226_max_iic_t = {0};
INA226TypeDef ina226_min_t = {0};
INA226TypeDef ina226_med_t = {0};
INA226TypeDef ina226_max_t = {0};
INA226_CXT_T ina226_cxt = {
    .ina226_t = {&ina226_min_t, &ina226_med_t, &ina226_max_t},
};

/**
 * @function: INA226_App_Measure_AllData
 * @brief This function is used to measure all data.
 * @param {uint8_t} channel: channel
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Measure_AllData(uint8_t channel)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    if (INA226_Obj_Get_Current(ina226_cxt.ina226_t[channel]) != 0)
    {
        printf("INA226_Obj_Get_Current failed! channel: [%d] Line: [%d] \r\n", channel, __LINE__);
        return 2;
    }
    if (INA226_Obj_Get_VbusVoltage(ina226_cxt.ina226_t[channel]) != 0)
    {
        printf("INA226_Obj_Get_VbusVoltage failed! channel: [%d] Line: [%d] \r\n", channel, __LINE__);
        return 2;
    }
    if (INA226_Obj_Get_ShuntVoltage(ina226_cxt.ina226_t[channel]) != 0)
    {
        printf("INA226_Obj_Get_ShuntVoltage failed! channel: [%d] Line: [%d] \r\n", channel, __LINE__);
        return 2;
    }
    if (INA226_Obj_Get_PowerIns(ina226_cxt.ina226_t[channel]) != 0)
    {
        printf("INA226_Obj_Get_PowerIns failed! channel: [%d] Line: [%d] \r\n", channel, __LINE__);
        return 2;
    }
    return 0;
}

/**
 * @function: INA226_App_Get_Current
 * @brief This function is used to get current.
 * @param {uint8_t} channel: channel
 * @param {double} *current: current. Unit: A
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Get_Current(uint8_t channel, double *current)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    *current = ina226_cxt.ina226_t[channel]->current;
    return 0;
}

/**
 * @function: INA226_App_Get_VbusVoltage
 * @brief This function is used to get Vbus voltage.
 * @param {uint8_t} channel: channel
 * @param {double} *voltage: voltage. Unit: V
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Get_VbusVoltage(uint8_t channel, double *voltage)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    *voltage = ina226_cxt.ina226_t[channel]->voltage;
    return 0;
}

/**
 * @function: INA226_App_Get_ShuntVoltage
 * @brief This function is used to get shunt voltage.
 * @param {uint8_t} channel: channel
 * @param {double} *voltage: voltage. Unit: V
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Get_ShuntVoltage(uint8_t channel, double *voltage)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    *voltage = ina226_cxt.ina226_t[channel]->shuntVoltage;
    return 0;
}

/**
 * @function: INA226_App_Get_PowerIns
 * @brief This function is used to get power ins.
 * @param {uint8_t} channel: channel
 * @param {double} *power: power. Unit: W
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Get_PowerIns(uint8_t channel, double *power)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    *power = ina226_cxt.ina226_t[channel]->power_ins;
    return 0;
}

/**
 * @function: INA226_App_Get_ID
 * @brief This function is used to get id.
 * @param {uint8_t} channel: channel
 * @param {uint16_t} *devid: device id.
 * @return {uint8_t} 0: success, Other: failed
 */
uint8_t INA226_App_Get_ID(uint8_t channel, uint16_t *devid)
{
    if (channel >= INA226_NUMBER)
    {
        return 1;
    }
    *devid = ina226_cxt.ina226_t[channel]->id;
    return 0;
}

/**
 * @function: INA226_App_Init
 * @brief This function is used to initializa INA226.
 * @return {void}
 */
void INA226_App_Init(void)
{
    uint8_t result = 0;
    ina226_min_iic_t.SCL_GPIOx = INA226_1_SCL_GPIO_Port;
    ina226_min_iic_t.SCL_GPIO_Pin = INA226_1_SCL_Pin;
    ina226_min_iic_t.SDA_GPIOx = INA226_1_SDA_GPIO_Port;
    ina226_min_iic_t.SDA_GPIO_Pin = INA226_1_SDA_Pin;
    ina226_min_t.Cfg_register = INA266_CFG_REG(0, 2, 6, 6, 7);
    ina226_min_t.Calibration_value = (uint16_t)INA226_MIN_CAL_VALUE;
    ina226_min_t.pIIC_Struct = &ina226_min_iic_t;
    ina226_min_t.current_lsb = INA226_MIN_CURRENT_LSB;
    ina226_min_t.addr = 0x80;
    result = INA226_Obj_Init(&ina226_min_t);
    if (result != 0)
    {
        printf("INA226_Obj_Init failed! Line: [%d] \r\n", __LINE__);
    }
    else
    {
        printf("INA226 MIN id 0x%04X \r\n", ina226_min_t.id);
    }

    ina226_med_iic_t.SCL_GPIOx = INA226_2_SCL_GPIO_Port;
    ina226_med_iic_t.SCL_GPIO_Pin = INA226_2_SCL_Pin;
    ina226_med_iic_t.SDA_GPIOx = INA226_2_SDA_GPIO_Port;
    ina226_med_iic_t.SDA_GPIO_Pin = INA226_2_SDA_Pin;
    ina226_med_t.Cfg_register = INA266_CFG_REG(0, 2, 6, 6, 7);
    ina226_med_t.Calibration_value = INA226_MED_CAL_VALUE;
    ina226_med_t.pIIC_Struct = &ina226_med_iic_t;
    ina226_med_t.current_lsb = INA226_MED_CURRENT_LSB;
    ina226_med_t.addr = 0x80;
    result = INA226_Obj_Init(&ina226_med_t);
    if (result != 0)
    {
        printf("INA226_Obj_Init failed! Line: [%d] \r\n", __LINE__);
    }
    else
    {
        printf("INA226 MED id 0x%04X \r\n", ina226_med_t.id);
    }

    ina226_max_iic_t.SCL_GPIOx = INA226_3_SCL_GPIO_Port;
    ina226_max_iic_t.SCL_GPIO_Pin = INA226_3_SCL_Pin;
    ina226_max_iic_t.SDA_GPIOx = INA226_3_SDA_GPIO_Port;
    ina226_max_iic_t.SDA_GPIO_Pin = INA226_3_SDA_Pin;

    ina226_max_t.Cfg_register = INA266_CFG_REG(0, 2, 6, 6, 7);
    ina226_max_t.Calibration_value = INA226_MAX_CAL_VALUE;
    ina226_max_t.pIIC_Struct = &ina226_max_iic_t;
    ina226_max_t.current_lsb = INA226_MAX_CURRENT_LSB;
    ina226_max_t.addr = 0x80;
    result = INA226_Obj_Init(&ina226_max_t);
    if (result != 0)
    {
        printf("INA226_Obj_Init failed! Line: [%d] \r\n", __LINE__);
    }
    else
    {
        printf("INA226 MAX id 0x%04X \r\n", ina226_max_t.id);
    }
}


void INA226_Addr_test(void)
{
    uint8_t index = 0;
    uint8_t find_num = 0;

    SoftAnalogIIC_Typedef *pIIC_Struct = &ina226_max_iic_t;

    for (index = 0; index < 0xFF; index++)
    {
        SoftAnalogIIC_Start(pIIC_Struct);
        SoftAnalogIIC_Send_Byte(pIIC_Struct, index);
        if (SoftAnalogIIC_Wait_Ack(pIIC_Struct) == IIC_OK)
        {
            find_num++;
            printf("Addr: [%d] \r\n", index);
            SoftAnalogIIC_Stop(pIIC_Struct);
        }
    }
    if (find_num == 0)
    {
        printf("No device found!");
    }
}



